/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.android.stk;

import com.android.*;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.telephony.TelephonyManager;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.RemoteViews;
import android.widget.TextView;
import android.widget.Toast;
import android.util.Log;

import com.android.internal.telephony.gsm.stk.AppInterface;
import com.android.internal.telephony.gsm.stk.Menu;
import com.android.internal.telephony.gsm.stk.Item;
import com.android.internal.telephony.gsm.stk.ResultCode;
import com.android.internal.telephony.gsm.stk.StkCmdMessage;
import com.android.internal.telephony.gsm.stk.StkCmdMessage.BrowserSettings;
import com.android.internal.telephony.gsm.stk.StkLog;
import com.android.internal.telephony.gsm.stk.StkResponseMessage;
import com.android.internal.telephony.gsm.stk.TextMessage;

import java.util.LinkedList;

/**
 * SIM toolkit application level service. Interacts with Telephopny messages,
 * application's launch and user input from STK UI elements.
 *
 */
public class StkAppService extends Service implements Runnable {

    // members
    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
    private AppInterface mStkService;
    private Context mContext = null;
    private StkCmdMessage mMainCmd = null;
    private StkCmdMessage mCurrentCmd = null;
    private Menu mCurrentMenu = null;
    private String lastSelectedItem = null;
    private boolean mMenuIsVisibile = false;
    private boolean responseNeeded = true;
    private boolean mCmdInProgress = false;
    private NotificationManager mNotificationManager = null;
    private LinkedList<DelayedCmd> mCmdsQ = null;
    private boolean launchBrowser = false;
    private BrowserSettings mBrowserSettings = null;
    static StkAppService sInstance = null;

    // Used for setting FLAG_ACTIVITY_NO_USER_ACTION when
    // creating an intent.
    private enum InitiatedByUserAction {
        yes,            // The action was started via a user initiated action
        unknown,        // Not known for sure if user initated the action
    }

    // constants
    static final String OPCODE = "op";
    static final String CMD_MSG = "cmd message";
    static final String RES_ID = "response id";
    static final String MENU_SELECTION = "menu selection";
    static final String INPUT = "input";
    static final String HELP = "help";
    static final String CONFIRMATION = "confirm";

    // operations ids for different service functionality.
    static final int OP_CMD = 1;
    static final int OP_RESPONSE = 2;
    static final int OP_LAUNCH_APP = 3;
    static final int OP_END_SESSION = 4;
    static final int OP_BOOT_COMPLETED = 5;
    private static final int OP_DELAYED_MSG = 6;

    // Response ids
    static final int RES_ID_MENU_SELECTION = 11;
    static final int RES_ID_INPUT = 12;
    static final int RES_ID_CONFIRM = 13;
    static final int RES_ID_DONE = 14;

    static final int RES_ID_TIMEOUT = 20;
    static final int RES_ID_BACKWARD = 21;
    static final int RES_ID_END_SESSION = 22;
    static final int RES_ID_EXIT = 23;

    private static final String PACKAGE_NAME = "cn.android.stk";
    private static final String MENU_ACTIVITY_NAME =
                                        PACKAGE_NAME + ".StkMenuActivity";
    private static final String INPUT_ACTIVITY_NAME =
                                        PACKAGE_NAME + ".StkInputActivity";

    // Notification id used to display Idle Mode text in NotificationManager.
    private static final int STK_NOTIFICATION_ID = 333;

    // Inner class used for queuing telephony messages (proactive commands,
    // session end) while the service is busy processing a previous message.
    private class DelayedCmd {
        // members
        int id;
        StkCmdMessage msg;

        DelayedCmd(int id, StkCmdMessage msg) {
            this.id = id;
            this.msg = msg;
        }
    }

    @Override
    public void onCreate() {
Log.i("mystk","mystk oncreate");
            // Initialize members
            mStkService = com.android.internal.telephony.gsm.stk.StkService
                    .getInstance();
Log.i("mystk","stkappservice  mStkService="+mStkService);
            // NOTE mStkService is a singleton and continues to exist even if the GSMPhone is disposed
            //   after the radio technology change from GSM to CDMA so the PHONE_TYPE_CDMA check is
            //   needed. In case of switching back from CDMA to GSM the GSMPhone constructor updates
            //   the instance. (TODO: test).
            if ((mStkService == null)
                    && (TelephonyManager.getDefault().getPhoneType()
                                    != TelephonyManager.PHONE_TYPE_CDMA)) {
                StkLog.d(this, " Unable to get Service handle");
                return;
            }

            mCmdsQ = new LinkedList<DelayedCmd>();
            Thread serviceThread = new Thread(null, this, "Stk App Service");
            serviceThread.start();
            mContext = getBaseContext();
            mNotificationManager = (NotificationManager) mContext
                    .getSystemService(Context.NOTIFICATION_SERVICE);
            sInstance = this;
Log.i("mystk","sInstance="+sInstance);

    }
    @Override
    public void onStart(Intent intent, int startId) {
Log.i("mystk","mystk onstart");

            waitForLooper();
Log.i("mystk","mystk onstart1");
            Bundle args = intent.getExtras();
Log.i("mystk","mystk onstart2");
            if (args == null) {
                return;
            }
Log.i("mystk","mystk onstart3");
            Message msg = mServiceHandler.obtainMessage();
Log.i("mystk","mystk onstart4");
            msg.arg1 = args.getInt(OPCODE);
Log.i("mystk","mystk onstart5"+msg.arg1);
            switch(msg.arg1) {
            case OP_CMD:
                msg.obj = args.getParcelable(CMD_MSG);
                break;
            case OP_RESPONSE:
                msg.obj = args;
                /* falls through */
            case OP_LAUNCH_APP:
            case OP_END_SESSION:
            case OP_BOOT_COMPLETED:
                break;
            default:
                return;
            }
Log.i("mystk","mystk onstart6");
            mServiceHandler.sendMessage(msg);
Log.i("mystk","mystk onstart7");
    }

    @Override
    public void onDestroy() {
Log.i("mystk","mystk onDestroy");

      waitForLooper();
           mServiceLooper.quit();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    public void run() {
Log.i("mystk","thread run");

      Looper.prepare();

           mServiceLooper = Looper.myLooper();
           mServiceHandler = new ServiceHandler();

           Looper.loop();

    }

    /*
     * Package api used by StkMenuActivity to indicate if its on the foreground.
     */
    void indicateMenuVisibility(boolean visibility) {
        mMenuIsVisibile = visibility;
    }

    /*
     * Package api used by StkMenuActivity to get its Menu parameter.
     */
    Menu getMenu() {
        return mCurrentMenu;
    }

    /*
     * Package api used by UI Activities and Dialogs to communicate directly
     * with the service to deliver state information and parameters.
     */
    static StkAppService getInstance() {
        return sInstance;
    }

    private void waitForLooper() {
Log.i("mystk","mystk waitForLooper start");
Log.i("mystk","mystk waitForLooper :mServiceHandler="+mServiceHandler);
        while (mServiceHandler == null) {
mServiceHandler=new ServiceHandler();
Log.i("mystk","mystk waitForLooper wait");
            synchronized (this) {
                try {
                    wait(100);
                } catch (InterruptedException e) {
                }
            }
        }
Log.i("mystk","mystk waitForLooper end");
    }

    private final class ServiceHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
Log.i("mystk","mystk handleMessage");

                int opcode = msg.arg1;
Log.i("mystk","mystk handleMessage  opcode="+msg.arg1);
                switch (opcode) {
                case OP_LAUNCH_APP:
Log.i("mystk","mystk handleMessage mMainCmd="+mMainCmd);
                    //if (mMainCmd == null) {
                        //// nothing todo when no SET UP MENU command didn't arrive.
                        //return;
                    //}
Log.i("mystk","mystk handleMessage launchMenuActivity1");
                    launchMenuActivity(null);
Log.i("mystk","mystk handleMessage launchMenuActivity2");
                    break;
                case OP_CMD:
                    StkCmdMessage cmdMsg = (StkCmdMessage) msg.obj;
                    // There are two types of commands:
                    // 1. Interactive - user's response is required.
                    // 2. Informative - display a message, no interaction with the user.
                    //
                    // Informative commands can be handled immediately without any delay.
                    // Interactive commands can't override each other. So if a command
                    // is already in progress, we need to queue the next command until
                    // the user has responded or a timeout expired.
                    if (!isCmdInteractive(cmdMsg)) {
                        handleCmd(cmdMsg);
                    } else {
                        if (!mCmdInProgress) {
                            mCmdInProgress = true;
                            handleCmd((StkCmdMessage) msg.obj);
                        } else {
                            mCmdsQ.addLast(new DelayedCmd(OP_CMD,
                                    (StkCmdMessage) msg.obj));
                        }
                    }
                    break;
                case OP_RESPONSE:
                    if (responseNeeded) {
                        handleCmdResponse((Bundle) msg.obj);
                    }
                    // call delayed commands if needed.
                    if (mCmdsQ.size() != 0) {
                        callDelayedMsg();
                    } else {
                        mCmdInProgress = false;
                    }
                    // reset response needed state var to its original value.
                    responseNeeded = true;
                    break;
                case OP_END_SESSION:
                    if (!mCmdInProgress) {
                        mCmdInProgress = true;
                        handleSessionEnd();
                    } else {
                        mCmdsQ.addLast(new DelayedCmd(OP_END_SESSION, null));
                    }
                    break;
                case OP_BOOT_COMPLETED:
                    StkLog.d(this, "OP_BOOT_COMPLETED");
                    if (mMainCmd == null) {
                        StkAppInstaller.unInstall(mContext);
                    }
                    break;
                case OP_DELAYED_MSG:
                    handleDelayedCmd();
                    break;
                }
            
        }
    }

    private boolean isCmdInteractive(StkCmdMessage cmd) {
Log.i("mystk","mystk isCmdInteractive");

        switch (cmd.getCmdType()) {
            case SEND_DTMF:
            case SEND_SMS:
            case SEND_SS:
            case SEND_USSD:
            case SET_UP_IDLE_MODE_TEXT:
            case SET_UP_MENU:
                return false;
            }

            return true;

    }

    private void handleDelayedCmd() {
Log.i("mystk","mystk handleDelayedCmd");


            if (mCmdsQ.size() != 0) {
                DelayedCmd cmd = mCmdsQ.poll();
                switch (cmd.id) {
                case OP_CMD:
                    handleCmd(cmd.msg);
                    break;
                case OP_END_SESSION:
                    handleSessionEnd();
                    break;
                }
            }
        

    }

    private void callDelayedMsg() {
Log.i("mystk","mystk callDelayedMsg");
 

            Message msg = mServiceHandler.obtainMessage();
            msg.arg1 = OP_DELAYED_MSG;
            mServiceHandler.sendMessage(msg);
        

    }

    private void handleSessionEnd() {
Log.i("mystk","mystk handleSessionEnd");


            mCurrentCmd = mMainCmd;
            lastSelectedItem = null;
            // In case of SET UP MENU command which removed the app, don't
            // update the current menu member.
            if (mCurrentMenu != null && mMainCmd != null) {
                mCurrentMenu = mMainCmd.getMenu();
            }
            if (mMenuIsVisibile) {
                launchMenuActivity(null);
            }
            if (mCmdsQ.size() != 0) {
                callDelayedMsg();
            } else {
                mCmdInProgress = false;
            }
            // In case a launch browser command was just confirmed, launch that url.
            if (launchBrowser) {
                launchBrowser = false;
                launchBrowser(mBrowserSettings);
            }
        

    }

    private void handleCmd(StkCmdMessage cmdMsg) {
Log.i("mystk","mystk handleCmd");


            if (cmdMsg == null) {
                return;
            }
            // save local reference for state tracking.
            mCurrentCmd = cmdMsg;
            boolean waitForUsersResponse = true;

            StkLog.d(this, cmdMsg.getCmdType().name());
            switch (cmdMsg.getCmdType()) {
            case DISPLAY_TEXT:
                TextMessage msg = cmdMsg.geTextMessage();
                responseNeeded = msg.responseNeeded;
                if (lastSelectedItem != null) {
                    msg.title = lastSelectedItem;
                } else if (mMainCmd != null){
                    msg.title = mMainCmd.getMenu().title;
                } else {
                    // TODO: get the carrier name from the SIM
                    msg.title = "";
                }
                launchTextDialog();
                break;
            case SELECT_ITEM:
                mCurrentMenu = cmdMsg.getMenu();
                launchMenuActivity(cmdMsg.getMenu());
                break;
            case SET_UP_MENU:
                mMainCmd = mCurrentCmd;
                mCurrentMenu = cmdMsg.getMenu();
                if (removeMenu()) {
                    StkLog.d(this, "Uninstall App");
                    mCurrentMenu = null;
                    StkAppInstaller.unInstall(mContext);
                } else {
                    StkLog.d(this, "Install App");
                    StkAppInstaller.install(mContext);
                }
                if (mMenuIsVisibile) {
                    launchMenuActivity(null);
                }
                break;
            case GET_INPUT:
            case GET_INKEY:
                launchInputActivity();
                break;
            case SET_UP_IDLE_MODE_TEXT:
                waitForUsersResponse = false;
                launchIdleText();
                break;
            case SEND_DTMF:
            case SEND_SMS:
            case SEND_SS:
            case SEND_USSD:
                waitForUsersResponse = false;
                launchEventMessage();
                break;
            case LAUNCH_BROWSER:
                launchConfirmationDialog(mCurrentCmd.geTextMessage());
                break;
            case SET_UP_CALL:
                launchConfirmationDialog(mCurrentCmd.getCallSettings().confirmMsg);
                break;
            case PLAY_TONE:
                launchToneDialog();
                break;
            }

            if (!waitForUsersResponse) {
                if (mCmdsQ.size() != 0) {
                    callDelayedMsg();
                } else {
                    mCmdInProgress = false;
                }
            }

    }

    private void handleCmdResponse(Bundle args) {
Log.i("mystk","mystk handleCmdResponse");


            if (mCurrentCmd == null) {
                return;
            }
            StkResponseMessage resMsg = new StkResponseMessage(mCurrentCmd);

            // set result code
            boolean helpRequired = args.getBoolean(HELP, false);

            switch(args.getInt(RES_ID)) {
            case RES_ID_MENU_SELECTION:
                StkLog.d(this, "RES_ID_MENU_SELECTION");
                int menuSelection = args.getInt(MENU_SELECTION);
                switch(mCurrentCmd.getCmdType()) {
                case SET_UP_MENU:
                case SELECT_ITEM:
                    lastSelectedItem = getItemName(menuSelection);
                    if (helpRequired) {
                        resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
                    } else {
                        resMsg.setResultCode(ResultCode.OK);
                    }
                    resMsg.setMenuSelection(menuSelection);
                    break;
                }
                break;
            case RES_ID_INPUT:
                StkLog.d(this, "RES_ID_INPUT");
                String input = args.getString(INPUT);
                if (mCurrentCmd.geInput().yesNo) {
                    boolean yesNoSelection = input
                            .equals(StkInputActivity.YES_STR_RESPONSE);
                    resMsg.setYesNo(yesNoSelection);
                } else {
                    if (helpRequired) {
                        resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
                    } else {
                        resMsg.setResultCode(ResultCode.OK);
                        resMsg.setInput(input);
                    }
                }
                break;
            case RES_ID_CONFIRM:
                StkLog.d(this, "RES_ID_CONFIRM");
                boolean confirmed = args.getBoolean(CONFIRMATION);
                switch (mCurrentCmd.getCmdType()) {
                case DISPLAY_TEXT:
                    resMsg.setResultCode(confirmed ? ResultCode.OK
                            : ResultCode.UICC_SESSION_TERM_BY_USER);
                    break;
                case LAUNCH_BROWSER:
                    resMsg.setResultCode(confirmed ? ResultCode.OK
                            : ResultCode.UICC_SESSION_TERM_BY_USER);
                    if (confirmed) {
                        launchBrowser = true;
                        mBrowserSettings = mCurrentCmd.getBrowserSettings();
                    }
                    break;
                case SET_UP_CALL:
                    resMsg.setResultCode(ResultCode.OK);
                    resMsg.setConfirmation(confirmed);
                    if (confirmed) {
                        launchCallMsg();
                    }
                    break;
                }
                break;
            case RES_ID_DONE:
                resMsg.setResultCode(ResultCode.OK);
                break;
            case RES_ID_BACKWARD:
                StkLog.d(this, "RES_ID_BACKWARD");
                resMsg.setResultCode(ResultCode.BACKWARD_MOVE_BY_USER);
                break;
            case RES_ID_END_SESSION:
                StkLog.d(this, "RES_ID_END_SESSION");
                resMsg.setResultCode(ResultCode.UICC_SESSION_TERM_BY_USER);
                break;
            case RES_ID_TIMEOUT:
                StkLog.d(this, "RES_ID_TIMEOUT");
                resMsg.setResultCode(ResultCode.NO_RESPONSE_FROM_USER);
                break;
            default:
                StkLog.d(this, "Unknown result id");
                return;
            }
            mStkService.onCmdResponse(resMsg);
        

    }

    /**
     * Returns 0 or FLAG_ACTIVITY_NO_USER_ACTION, 0 means the user initiated the action.
     *
     * @param userAction If the userAction is yes then we always return 0 otherwise
     * mMenuIsVisible is used to determine what to return. If mMenuIsVisible is true
     * then we are the foreground app and we'll return 0 as from our perspective a
     * user action did cause. If it's false than we aren't the foreground app and
     * FLAG_ACTIVITY_NO_USER_ACTION is returned.
     *
     * @return 0 or FLAG_ACTIVITY_NO_USER_ACTION
     */
    private int getFlagActivityNoUserAction(InitiatedByUserAction userAction) {
        return ((userAction == InitiatedByUserAction.yes) | mMenuIsVisibile) ?
                                                    0 : Intent.FLAG_ACTIVITY_NO_USER_ACTION;
    }

    private void launchMenuActivity(Menu menu) {
Log.i("mystk","mystk launchMenuActivity");


            Intent newIntent = new Intent(Intent.ACTION_VIEW);
            newIntent.setClassName(PACKAGE_NAME, MENU_ACTIVITY_NAME);
            int intentFlags = Intent.FLAG_ACTIVITY_NEW_TASK
                    | Intent.FLAG_ACTIVITY_CLEAR_TOP;
            if (menu == null) {
Log.i("mystk","mystk launchMenuActivity menu=null");
                // We assume this was initiated by the user pressing the tool kit icon
                intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.yes);

                newIntent.putExtra("STATE", StkMenuActivity.STATE_MAIN);
            } else {
Log.i("mystk","mystk launchMenuActivity menu!=null");
                // We don't know and we'll let getFlagActivityNoUserAction decide.
                intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.unknown);

                newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
            }
            newIntent.setFlags(intentFlags);
Log.i("mystk","mystk launchMenuActivity setflag");
try{
Log.i("mystk","newIntent=:"+newIntent);
Log.i("mystk"," launchMenuActivity  mcontenxt="+mContext);
if(mContext==null){
mContext = getBaseContext();
}
Log.i("mystk"," launchMenuActivity  mcontenxt="+mContext);
	mContext.startActivity(newIntent);

}catch (Exception e){
	Log.i("mystk","mystk launchMenuActivity err  "+e+" , message: ");
e.printStackTrace();
}
Log.i("mystk","mystk launchMenuActivity startActivity");

    }

    private void launchInputActivity() {
Log.i("mystk","mystk launchInputActivity");


            Intent newIntent = new Intent(Intent.ACTION_VIEW);
            newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                                | getFlagActivityNoUserAction(InitiatedByUserAction.unknown));
            newIntent.setClassName(PACKAGE_NAME, INPUT_ACTIVITY_NAME);
            newIntent.putExtra("INPUT", mCurrentCmd.geInput());
            mContext.startActivity(newIntent);
        

    }

    private void launchTextDialog() {
Log.i("mystk","mystk launchTextDialog");


            Intent newIntent = new Intent(this, StkDialogActivity.class);
            newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                    | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
                    | Intent.FLAG_ACTIVITY_NO_HISTORY
                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
                    | getFlagActivityNoUserAction(InitiatedByUserAction.unknown));
            newIntent.putExtra("TEXT", mCurrentCmd.geTextMessage());
            startActivity(newIntent);

    }

    private void launchEventMessage() {
Log.i("mystk","mystk launchEventMessage");


            TextMessage msg = mCurrentCmd.geTextMessage();
            if (msg == null) {
                return;
            }
            Toast toast = new Toast(mContext.getApplicationContext());
            LayoutInflater inflate = (LayoutInflater) mContext
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View v = inflate.inflate(R.layout.stk_event_msg, null);
            TextView tv = (TextView) v
                    .findViewById(com.android.internal.R.id.message);
            ImageView iv = (ImageView) v
                    .findViewById(com.android.internal.R.id.icon);
            if (msg.icon != null) {
                iv.setImageBitmap(msg.icon);
            } else {
                iv.setVisibility(View.GONE);
            }
            if (!msg.iconSelfExplanatory) {
                tv.setText(msg.text);
            }

            toast.setView(v);
            toast.setDuration(Toast.LENGTH_LONG);
            toast.setGravity(Gravity.BOTTOM, 0, 0);
            toast.show();

    }

    private void launchConfirmationDialog(TextMessage msg) {
Log.i("mystk","mystk launchConfirmationDialog");


            msg.title = lastSelectedItem;
            Intent newIntent = new Intent(this, StkDialogActivity.class);
            newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                    | Intent.FLAG_ACTIVITY_NO_HISTORY
                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
                    | getFlagActivityNoUserAction(InitiatedByUserAction.unknown));
            newIntent.putExtra("TEXT", msg);
            startActivity(newIntent);

    }

    private void launchBrowser(BrowserSettings settings) {
Log.i("mystk","mystk launchBrowser");


            if (settings == null) {
                return;
            }
            // Set browser launch mode
            Intent intent = new Intent();
            intent.setClassName("cn.android.browser",
                    "cn.android.browser.BrowserActivity");

            // to launch home page, make sure that data Uri is null.
            Uri data = null;
            if (settings.url != null) {
                data = Uri.parse(settings.url);
            }
            intent.setData(data);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            switch (settings.mode) {
            case USE_EXISTING_BROWSER:
                intent.setAction(Intent.ACTION_VIEW);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                break;
            case LAUNCH_NEW_BROWSER:
                intent.setAction(Intent.ACTION_VIEW);
                intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
                break;
            case LAUNCH_IF_NOT_ALREADY_LAUNCHED:
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                break;
            }
            // start browser activity
            startActivity(intent);
            // a small delay, let the browser start, before processing the next command.
            // this is good for scenarios where a related DISPLAY TEXT command is
            // followed immediately.
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {}
        

    }

    private void launchCallMsg() {
Log.i("mystk","mystk launchCallMsg");


            TextMessage msg = mCurrentCmd.getCallSettings().callMsg;
            if (msg.text == null || msg.text.length() == 0) {
                return;
            }
            msg.title = lastSelectedItem;

            Toast toast = Toast.makeText(mContext.getApplicationContext(), msg.text,
                    Toast.LENGTH_LONG);
            toast.setGravity(Gravity.BOTTOM, 0, 0);
            toast.show();

    }

    private void launchIdleText() {
Log.i("mystk","mystk launchIdleText");


            TextMessage msg = mCurrentCmd.geTextMessage();
            if (msg.text == null) {
                mNotificationManager.cancel(STK_NOTIFICATION_ID);
            } else {
                Notification notification = new Notification();
                RemoteViews contentView = new RemoteViews(
                        PACKAGE_NAME,
                        com.android.internal.R.layout.status_bar_latest_event_content);

                notification.flags |= Notification.FLAG_NO_CLEAR;
                notification.icon = com.android.internal.R.drawable.stat_notify_sim_toolkit;
                // Set text and icon for the status bar and notification body.
                if (!msg.iconSelfExplanatory) {
                    notification.tickerText = msg.text;
                    contentView.setTextViewText(com.android.internal.R.id.text,
                            msg.text);
                }
                if (msg.icon != null) {
                    contentView.setImageViewBitmap(com.android.internal.R.id.icon,
                            msg.icon);
                } else {
                    contentView
                            .setImageViewResource(
                                    com.android.internal.R.id.icon,
                                    com.android.internal.R.drawable.stat_notify_sim_toolkit);
                }
                notification.contentView = contentView;
                notification.contentIntent = PendingIntent.getService(mContext, 0,
                        new Intent(mContext, StkAppService.class), 0);

                mNotificationManager.notify(STK_NOTIFICATION_ID, notification);
            }
        

    }

    private void launchToneDialog() {
Log.i("mystk","mystk launchToneDialog");
 

            Intent newIntent = new Intent(this, ToneDialog.class);
            newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                    | Intent.FLAG_ACTIVITY_NO_HISTORY
                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
                    | getFlagActivityNoUserAction(InitiatedByUserAction.unknown));
            newIntent.putExtra("TEXT", mCurrentCmd.geTextMessage());
            newIntent.putExtra("TONE", mCurrentCmd.getToneSettings());
            startActivity(newIntent);
        

    }

    private String getItemName(int itemId) {
Log.i("mystk","mystk getItemName");


            Menu menu = mCurrentCmd.getMenu();
            if (menu == null) {
                return null;
            }
            for (Item item : menu.items) {
                if (item.id == itemId) {
                    return item.text;
                }
            }
            return null;

    }

    private boolean removeMenu() {
Log.i("mystk","mystk removeMenu");


            try {
                if (mCurrentMenu.items.size() == 1 &&
                    mCurrentMenu.items.get(0) == null) {
                    return true;
                }
            } catch (NullPointerException e) {
                StkLog.d(this, "Unable to get Menu's items size");
                return true;
            }
            return false;

    }
}
